package com.cellulam.framework.core.cocurrent;

import com.google.common.collect.Maps;

import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 要锁的对象的哈希值如果发生改变，可能导致锁无法释放
 *
 * @param <T>
 */
public class SegmentLock<T> {
    private Integer segments = 16;//默认分段数量
    private final Map<Integer, ReentrantLock> lockMap = Maps.newHashMap();

    public SegmentLock() {
        init(null, false);
    }

    public SegmentLock(Integer segments, boolean fair) {
        init(segments, fair);
    }

    private void init(Integer segments, boolean fair) {
        if (segments != null) {
            this.segments = segments;
        }
        for (int i = 0; i < this.segments; i++) {
            lockMap.put(i, new ReentrantLock(fair));
        }
    }

    public void lock(T object) {
        ReentrantLock lock = lockMap.get((object.hashCode() >>> 1) % this.segments);
        lock.lock();
    }

    public void unlock(T object) {
        ReentrantLock lock = lockMap.get((object.hashCode() >>> 1) % this.segments);
        lock.unlock();
    }
}
